<?php
namespace app\home\controller;
use think\Controller;
use think\Db;

/**
 * Redis 秒杀，队列测试
 */
class Redistest extends Controller{
	// reids连接参数
	protected $options = [
        'host'       => '127.0.0.1',
        'port'       => 6379,
        'password'   => 'yqy1994',
    ];

    // redis实例
    static $redis = null;

    // 构造函数
    public function __construct()
    {
    	parent::__construct();
		if(is_null(self::$redis)){
			$redis = new \Redis();
			$redis->connect($this->options['host'],$this->options['port']);
			$redis->auth($this->options['password']);
		}
		self::$redis = $redis;
    }

    // 秒杀接口API
    public function secKill()
    {
    	$goods_id = $this->request->param('goods_id');
    	$user_id = $this->userLogin();
    	$res = $this->setRedisUser($user_id);
    	
		// $res = self::createOrder($goods_id,$user_id);
    	// if($res){
    	// 	self::insertLog('时间：'.date('Y-m-d H:i:s').',用户秒杀成功：'.$user_id."\r\n",'success');
    	// }else{
    	// 	self::insertLog('时间：'.date('Y-m-d H:i:s').',用户秒杀失败：'.$user_id."\r\n",'error');
    	// }
    	return json_encode(['status'=>1,'msg'=>'抢购中...']);
    	
    }

    // 模拟用户登录
    public function userLogin()
    {
    	$uid = mt_rand(1,9999);
    	return $uid;
    }

    // 将用户存入redis队列
    public function setRedisUser($user_id)
    {
    	# 添加入队
    	return self::$redis->rpush('user_id',$user_id);
    }

    // 从排队队列中取出用户并判断是否存在与结果队列中
    static function checkUser()
    {
    	if(self::$redis->llen('user_id')){
    		$user_id = self::$redis->lpop('user_id');
    		# 如果结果队列已经存在200个用户，则无需继续执行
    		$finally_len = self::$redis->llen('finally');
    		if($finally_len > 200) return json_encode(['status'=>0,'msg'=>'抢购已结束,请注意查看订单']);
    		# 结果队列
    		$finally = self::$redis->lrange('finally',0,-1);
    		for ($i = 0; $i < self::$redis->llen('finally'); $i++) {
    			# 如果存在，则返回已抢购状态
	    		if($user_id === $finally[$i]) return false;
	    	}
	    	return $user_id;
    	}else{
    		self::insertLog('时间：'.$time.'--->无抢购的用户','error');
    		return false;
    	}
    }

    // 模拟下单
    public function createOrder()
    {
    	$goods_id = $this->request->param('goods_id');
    	$time = date('Y-m-d H:i:s',time());
    	# 查看结果队列中是否存在该用户
    	$user_id = self::checkUser();

    	if($user_id === false){
    		return json_encode(['status'=>0,'msg'=>'已存在结果队列中']);
    	} else {
	    	# 下单前检查redis队列库存量
	    	$res = self::checkRedisStock();
	    	if($res){
	    		# 如果为真，则生成订单
	    		$data['order_number'] = getNoncestr(6).time().$user_id;
	    		$data['goods_id'] = $goods_id;
	    		$data['create_time'] = time();
	    		$data['user_id'] = $user_id;
	    		$result = Db::name('order')->insert($data);
	    		if($result){
	    			# 减少库存
	    			$resu = Db::name('goods')->where('id',$goods_id)->setDec('stock');
	    			$count = self::$redis->llen('goods_stock');
	    			# 将该用户加入结果队列
	    			self::$redis->rpush('finally',$user_id);
	    			self::insertLog('时间：'.$time.',库存：'.$count."\r\n",'stock');
	    			return json_encode(['status'=>1,'msg'=>'下单成功']);
	    		}else{
	    			# 系统错误，加入订单失败
	    			self::insertLog('时间：'.$time.'，系统错误！'."\r\n",'error');
	    			return json_encode(['status'=>0,'msg'=>'下单失败']);
	    		}
	    	}else{
	    		# 如果为假，则生成日志
	    		//self::insertLog('时间：'.$time.'，库存不足！'."\r\n",'error');
	    		return json_encode(['status'=>0,'msg'=>'库存不足']);
	    	}
    	}
    }

    // 将抢购的商品库存  入队列
    public function setInRedis()
    {
    	$goods_id = $this->request->param('goods_id');
    	# 查询是否存在此产品
    	$goodInfo = Db::name('goods')->where('id',$goods_id)->field('id,stock')->find();
    	if(!$goodInfo) return false;

    	# 入队
    	$num = self::$redis->llen('goods_stock');
    	$count = $goodInfo['stock'] - $num;

    	for ($i = 0; $i < $count; $i++) { 
    		self::$redis->lpush('goods_stock',1);
    	}

    	echo self::$redis->llen('goods_stock');
    }

    // 判断redis队列库存量
    static function checkRedisStock()
    {
    	$time = date('Y-m-d H:i:s',time());
    	$count = self::$redis->lpop('goods_stock');
    	if(!$count){
    		//self::insertLog('时间：'.$time.',库存：'.$count."\r\n",'stock');
    		return false;
    	}else{
    		return true;
    	}
    }

    /**
     * 记录日志
     * @param $event 事件
     * @param $type 日志类型
     */
    static function insertLog($event,$type)
    {
    	if($type === 'success'){
    		# 成功下单日志
    		file_put_contents('./success.txt', $event,FILE_APPEND);
    	}elseif ($type === 'stock') {
    		# 失败操作记录
    		file_put_contents('./stock.txt', $event,FILE_APPEND);
    	}elseif ($type === 'error') {
    		# 失败操作记录
    		file_put_contents('./error.txt', $event,FILE_APPEND);
    	}
    }

}